package com.vhly.classfile;

import com.vhly.classfile.util.CPTool;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;

public class Field {

    private int access;
    private int name_index;
    private int sig_index;
    private int attribute_count;
    private Vector atts;
    private int constant;
    private ConstantValue cv;
    private ConstantPool cp;
    private boolean bSynthetic;

    public static Field createField(ConstantPool constantpool, String name, String type) {
        Field ret;
        int nindex = CPTool.addUTF8(constantpool,name);
        int tindex = CPTool.addUTF8(constantpool,type);
        ret = new Field(AccessFlag.ACC_PUBLIC, nindex, tindex, constantpool);
        return ret;
    }

    public Field(ConstantPool constantpool) {
        this(AccessFlag.ACC_PUBLIC, 0, 0, constantpool);
    }

    public Field(int acc, int nIndex, int typeIndex, ConstantPool constantpool) {
        access = acc;
        name_index = nIndex;
        sig_index = typeIndex;
        attribute_count = 0;
        atts = new Vector();
        constant = 0;
        cv = null;
        cp = constantpool;
        bSynthetic = false;
    }

    public int getAttributeCount() {
        attribute_count = atts.size();
        return attribute_count;
    }

    public void setAttributeCount(int s) {
        attribute_count = s;
    }

    public Attribute getAttribute(int i) {
        Attribute attribute = (Attribute) atts.elementAt(i);
        return attribute;
    }

    public boolean isSynthetic() {
        return bSynthetic;
    }

    public ConstantValue getConstantValue() {
        Object obj = null;
        if (atts.size() <= 0) {
            return null;
        } else {
            ConstantValue constantvalue = (ConstantValue) atts.elementAt(constant);
            cv = constantvalue;
            return cv;
        }
    }

    public void setConstantValue(ConstantValue cvv) {
        cv = cvv;
        if (atts.isEmpty())
            atts.add(cvv);
        else
            atts.setElementAt(cvv, constant);
    }

    public void setCVIndex(int i) {
        constant = i;
    }

    public int getCVIndex() {
        return constant;
    }

    public void read(DataInputStream datainputstream)
            throws IOException {
        access = datainputstream.readUnsignedShort();
        if (Debug.isEnabled())
            System.out.println((new StringBuilder()).append("  read Field Access :0x").append(Integer.toHexString(access)).toString());
        name_index = datainputstream.readUnsignedShort();
        if (Debug.isEnabled())
            System.out.println((new StringBuilder()).append("  read Field NameIndex :0x").append(Integer.toHexString(name_index)).toString());
        sig_index = datainputstream.readUnsignedShort();
        if (Debug.isEnabled())
            System.out.println((new StringBuilder()).append("  read Field SigIndex :0x").append(Integer.toHexString(sig_index)).toString());
        attribute_count = datainputstream.readUnsignedShort();
        if (Debug.isEnabled())
            System.out.println((new StringBuilder()).append("  read Field Attribute Count :0x").append(Integer.toHexString(attribute_count)).toString());
        if (attribute_count != 0) {
            for (int i = 0; i < attribute_count; i++) {
                int j = datainputstream.readUnsignedShort();
                CPUtf8 cputf8 = (CPUtf8) cp.getCPEntryAtIndex(j);
                String s = cputf8.getString();
                if (s.equals("ConstantValue")) {
                    ConstantValue constantvalue = new ConstantValue();
                    constantvalue.setNameIndex(j);
                    constantvalue.read(datainputstream, false);
                    atts.add(constantvalue);
                    continue;
                }
                if (s.equals("Synthetic")) {
                    Synthetic synthetic = new Synthetic();
                    synthetic.setNameIndex(j);
                    synthetic.read(datainputstream, false);
                    atts.add(synthetic);
                    bSynthetic = true;
                } else {
                    Unknown unknown = new Unknown();
                    unknown.setNameIndex(j);
                    unknown.read(datainputstream, false);
                    atts.add(unknown);
                }
            }

        }
    }

    public void write(DataOutputStream dataoutputstream)
            throws IOException {
        dataoutputstream.writeShort(access);
        dataoutputstream.writeShort(name_index);
        dataoutputstream.writeShort(sig_index);
        if (Debug.isEnabled()) {
            System.out.println((new StringBuilder()).append(" Field Write Access:").append(access).toString());
            System.out.println((new StringBuilder()).append(" Field Write Name Index:").append(name_index).toString());
            System.out.println((new StringBuilder()).append(" Field Write Sig Index:").append(sig_index).toString());
        }
        attribute_count = atts.size();
        dataoutputstream.writeShort(attribute_count);
        if (attribute_count != 0) {
            for (int i = 0; i < atts.size(); i++) {
                Attribute attribute = (Attribute) atts.elementAt(i);
                if (Debug.isEnabled()) {
                    System.out.println((new StringBuilder()).append("  Field Write Attribute Name INdex:").append(attribute.getNameIndex()).toString());
                    System.out.println((new StringBuilder()).append("  Field Write Attribute Data Len:").append(attribute.getDataLen()).toString());
                }
                System.out.println((new StringBuilder()).append("The Atts Size is ").append(atts.size()).append(" \nWrite an Attriubte").toString());
                attribute.write(dataoutputstream);
            }

        }
    }

    public String getName() {
        CPUtf8 cputf8 = (CPUtf8) cp.getCPEntryAtIndex(name_index);
        return cputf8.getString();
    }

    public void setName(String s) {
        if (s != null) {
            if (s.length() >= 1) {
                CPUtf8 cputf8 = (CPUtf8) cp.getCPEntryAtIndex(name_index);
                cputf8.setString(s);
            }
        }
    }

    public int getNameIndex() {
        return name_index;
    }

    public void setNameIndex(int i) {
        name_index = i;
    }

    public int getAccess() {
        return access;
    }

    public void setAccess(int i) {
        access = i;
    }

    public int getSigIndex() {
        return sig_index;
    }

    public String getSig() {
        CPUtf8 cputf8 = (CPUtf8) cp.getCPEntryAtIndex(sig_index);
        return cputf8.getString();
    }

    public void setSigIndex(int i) {
        sig_index = i;
    }

    public Enumeration getAttributes() {
        return atts.elements();
    }
}